package 实验五;

//RationalNumber.java Author:Lewis/Loftus
//Represents one rational number with a numerator and denominator.
public class RationalNumber implements Comparable
{
    private int numerator,denominator;
    //Constructor:Sets up the rational number by ensuring a nozero denominator and making only the numerator signed.
    public RationalNumber(int numer, int denom)
    {
        if (denom==0)
            denom = 1;
        //Make the numerator "store" the sign
        if (denom<0)
        {
            numer=numer*-1;
            denom=denom*-1;
        }
        numerator= numer;
        denominator = denom;
        reduce();
    }
    //Return the numerator of this rational number.
    public int getNumerator()
    {
        return numerator;
    }
    //Returns the denominator of this rational number.
    public int getDenominator()
    {
        return denominator;
    }
    //Returns the reciprocal of this rational number.
    public RationalNumber reciprocal()
    {
        return new RationalNumber(denominator,numerator);
    }
    //Adds this rational number to the one passed as a parameter.A common denominator is found by multiplying the indiviaual denominators.
    public RationalNumber add(RationalNumber op2)
    {
        int commonDenominator = denominator *op2.getDenominator();
        int numerator1 = numerator*op2.getDenominator();
        int numerator2 = op2.getNumerator()*denominator;
        int sum = numerator1 + numerator2;

        return new RationalNumber(sum,commonDenominator);
    }
    //Subtracts the rational number passed as a parmeter from this rational number.
    public RationalNumber subtract(RationalNumber op2)
    {
        int commonDenominator = denominator*op2.getDenominator();
        int numerator1 = numerator*op2.getDenominator();
        int numerator2 = op2.getNumerator()*denominator;
        int difference = numerator1-numerator2;

        return new RationalNumber(difference,commonDenominator);
    }
    //Mulitiplies this rational number by the one passed as a parameter.
    public RationalNumber multiply(RationalNumber op2)
    {
        int numer = numerator*op2.getNumerator();
        int denom = denominator*op2.getDenominator();

        return new RationalNumber(numer,denom);
    }
    //Divides this rational numer by the one passed as a parameter by multiplying by the reciorocal of the second rational.
    public RationalNumber divide(RationalNumber op2)
    {
        return multiply(op2.reciprocal());
    }
    //Determines if  this rational number is equal to the one passed as a parameter .Assumes
    //they are both reduced.
    public boolean isLike(RationalNumber op2)
    {
        return(numerator == op2.getNumerator() && denominator == op2.getDenominator());
    }
    //Returns this rational number as a string.
    public String toString()
    {
        String result;
        if (numerator == 0)
            result = "0";
        else
        if(denominator == 1)
            result = numerator+"";
        else
            result = numerator + "/"+denominator;
        return result;
    }
    //Reduces this rational number by dividing both the numerator and the denominator by their greatest common divisor.
    public void reduce()
    {
        if (numerator != 0)
        {
            int common = gcd(Math.abs(numerator),denominator);

            numerator = numerator/common;
            denominator = denominator/common;
        }
    }
    //Computes and returns the greatest common divisor of two positive parameters.
    //uses Euclid's algorithm.
    private int gcd(int num1,int num2)
    {
        while (num1 !=num2)
            if (num1 > num2)
                num1= num1-num2;
            else
                num2 =num2-num1;

        return num1;
    }
    //Comparing two rational numbers with error accuracy of 0.0001.
    public int compareTo(Object obj)
    {
        float a ;
        RationalNumber op2 = (RationalNumber)obj;
        RationalNumber temp = this.subtract(op2);
        a =(float)(temp.getNumerator()/temp.getDenominator());

        if (a>0){
            if(a<=0.0001)
                return 0;
            else
                return 1;
        }else
        if(a<0){
            if(a>=-0.0001)
                return 0;
            else
                return -1;
        }else
            return 0;
    }
}